import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import javax.xml.parsers.*;
import org.xml.sax.InputSource;
import org.w3c.dom.*;
import java.io.*;


public class MyXMLParser implements Runnable {
	private Queue<String> myQueue;
	private ArrayList<Data> dataStorage;
	private boolean processingQueue;
	private String xml;
	private DataStorer dataSaver;
	private MyExtrapolation extrapolator;

	public MyXMLParser(DataStorer saver) {
		setMyQueue(new LinkedList<String>());
		processingQueue = false;
		dataSaver = saver;
		extrapolator = new MyExtrapolation();
	}

	private void setMyQueue(Queue<String> myQueue) {
		this.myQueue = myQueue;
	}

	public void queue(String arg0) {	

		myQueue.add(arg0);

		if (!processingQueue) {
			new Thread(this).start();
			processingQueue = true;
		}
	}

	public static String ElementToString(Element e) {
		Node child = e.getFirstChild();
		if (child instanceof CharacterData) {
			CharacterData cd = (CharacterData) child;
			return cd.getData();
		}
		return "" + Integer.MIN_VALUE;
	}

	@Override
	public void run() {

		while (!myQueue.isEmpty()) {
			try {

				DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
				DocumentBuilder db = dbf.newDocumentBuilder();
				InputSource is = new InputSource();
				xml = myQueue.poll();
				is.setCharacterStream(new StringReader(xml));

				Document doc = db.parse(is);
				NodeList nodes = doc.getElementsByTagName("MEASUREMENT");

				dataStorage = new ArrayList<Data>();

				//Parsing of the XML stream

				for (int i = 0; i < nodes.getLength(); i++) {
					Data weatherData = new Data();
					Element element = (Element) nodes.item(i);

					NodeList STN = element.getElementsByTagName("STN");
					Element line = (Element) STN.item(0);
					Integer station = Integer.parseInt(ElementToString(line));
					weatherData.setStn(station);

					NodeList DATE = element.getElementsByTagName("DATE");
					line = (Element) DATE.item(0);
					weatherData.setDate(ElementToString(line));

					NodeList TIME = element.getElementsByTagName("TIME");
					line = (Element) TIME.item(0);
					weatherData.setTime(ElementToString(line));

					NodeList TEMP = element.getElementsByTagName("TEMP");
					line = (Element) TEMP.item(0);
					weatherData.setTemp(validateValue(Double.parseDouble(ElementToString(line)), "TEMP", station));

					NodeList DEWP = element.getElementsByTagName("DEWP");
					line = (Element) DEWP.item(0);
					weatherData.setDewp(validateValue(Double.parseDouble(ElementToString(line)), "DEWP", station));

					NodeList STP = element.getElementsByTagName("STP");
					line = (Element) STP.item(0);
					weatherData.setStp(validateValue(Double.parseDouble(ElementToString(line)), "STP", station));

					NodeList SLP = element.getElementsByTagName("SLP");
					line = (Element) SLP.item(0);
					weatherData.setSlp(validateValue(Double.parseDouble(ElementToString(line)), "SLP", station));

					NodeList VISIB = element.getElementsByTagName("VISIB");
					line = (Element) VISIB.item(0);
					weatherData.setVisib(validateValue(Double.parseDouble(ElementToString(line)), "VISIB", station));

					NodeList WDSP = element.getElementsByTagName("WDSP");
					line = (Element) WDSP.item(0);
					weatherData.setWdsp(validateValue(Double.parseDouble(ElementToString(line)), "WDSP", station));

					NodeList PRCP = element.getElementsByTagName("PRCP");
					line = (Element) PRCP.item(0);
					weatherData.setPrcp(validateValue(Double.parseDouble(ElementToString(line)), "PRCP", station));

					NodeList SNDP = element.getElementsByTagName("SNDP");
					line = (Element) SNDP.item(0);
					weatherData.setSndp(validateValue(Double.parseDouble(ElementToString(line)), "SNDP", station));

					NodeList FRSHTT = element.getElementsByTagName("FRSHTT");
					line = (Element) FRSHTT.item(0);
					weatherData.setFrshtt(ElementToString(line));

					NodeList CLDC = element.getElementsByTagName("CLDC");
					line = (Element) CLDC.item(0);
					weatherData.setCldc(validateValue(Double.parseDouble(ElementToString(line)), "CLDC", station));

					NodeList WNDDIR = element.getElementsByTagName("WNDDIR");
					line = (Element) WNDDIR.item(0);
					weatherData.setWnddir(Integer.parseInt(ElementToString(line)));

					dataStorage.add(weatherData);
				}

				//Once the data is checked it can be saved to the database.
				for (Data data : dataStorage) {
					dataSaver.add(data);
				}

							
			} catch (Exception e) {
				e.printStackTrace();
				//System.out.println(xml);
			}
			


		}

		//Done with Queue... As long as the object exists it will wait for something to fill up his queue again
		processingQueue = false;
	}

	private Double validateValue(Double value, String type, Integer station) {
		Double last = null;
		ArrayList<Double> extrapoList = null; //MUST BE INITIALIZED
		
////		//Missing value
////		if (value == Integer.MIN_VALUE) {
////			
////			extrapoList = dataSaver.getHistory(type.toLowerCase(), station);
////						
////			if (extrapoList.size() > 0) 
////				last = extrapoList.get(extrapoList.size()-1);
////			else
////				return 0.0;
////			
////			extrapolator.setDouble(extrapoList);
////			
////			return last += extrapolator.growth();
////		}
//
//		//20% Deviation from usual growth.
//		
//		if (type.toLowerCase().equals("temp")) {
//			extrapoList = dataSaver.getHistory(type.toLowerCase(), station);
//			
//			if (extrapoList.size() > 0) {
//				last = extrapoList.get(extrapoList.size()-1);
//				if (value > last*1.2) {
//					return last*1.2;
//				}
//			}				
//		}
		return 0.0;
		//Nothing's wrong
		//return value;
	}



}
